package com.leyou.item.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.Jshop.common.pojo.PageResult;
import com.leyou.item.bo.SpuBo;
import com.leyou.item.mapper.*;
import com.leyou.item.pojo.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/**
 * 所有商品相关的业务都在此类解决
 * */

@Service
public class GoodService {

    //需要查询SPU信息
    @Autowired
    private SpuMapper spuMapper;

    //需要查询分类信息
    @Autowired
    private CategoryService categoryService;

    //需要查询品牌信息
    @Autowired
    private BrandMapper brandMapper;

    //需要新增sku
    @Autowired
    private SkuMapper skuMapper;

    //需要同步spuDetail
    @Autowired
    private SpuDetailMapper spuDetailMapper;

    //需要查询sku的库存
    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;



    //分页查询SPU信息
    public PageResult<SpuBo> querySpuByPage(String key, Boolean saleable, Integer page, Integer rows){

        //自然是要模糊查询那套了
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();

        //所有非必须的参数都需要进行判空!

        //设置搜索条件：模糊匹配、与saleable一致的
        if (StringUtils.isNotBlank(key)){
            criteria.andLike("title","%" + key + "%");
        }
        if (saleable != null){
            criteria.andEqualTo("saleable",saleable);
        }

        //设置分页条件
        //非静态类的静态方法直接调用 返回Page对象
        PageHelper.startPage(page,rows);

        //执行查询
        List<Spu> spus = this.spuMapper.selectByExample(example);
        PageInfo<Spu> pageInfo = new PageInfo<>(spus);

        //将spus-->spuBos
        List<SpuBo> spuBos = new ArrayList<>();

        spus.forEach(spu -> {
            SpuBo spuBo = new SpuBo();
            //copy共同属性的值到新的对象
            BeanUtils.copyProperties(spu,spuBo);

            //查询前端页面需要的分类名称
            //mapper需要继承SelectByIdListMapper<Category,Long>
            List<String> cNames = this.categoryService.queryNamesByCid(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));

            //返回前端的是 "一级/二级/三级"
            spuBo.setCname(StringUtils.join(cNames,"/"));

            //查询品牌名称
            Brand brand = this.brandMapper.selectByPrimaryKey(spu.getBrandId());
            spuBo.setBname(brand.getName());
            spuBos.add(spuBo);
        });

        return new PageResult<>(pageInfo.getTotal(),spuBos);

    }

    //新增商品 逻辑比较复杂，我们除了要对SPU新增以外，还要对SpuDetail、Sku、Stock进行同步
    //接受对象为SPU扩展版SpuBo
    @Transactional
    public void saveGoods(SpuBo spuBo){

        //新增spu
        //对未传过来的字段设置默认值

        //防止SQL注入超大ID导致溢出
        spuBo.setId(null);

        spuBo.setSaleable(true);
        spuBo.setValid(true);
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        this.spuMapper.insertSelective(spuBo);


        //新增spuDetail

        SpuDetail spuDetail = spuBo.getSpuDetail();
        //此处不是null，上面insertSelective(spuBo)执行成功后会返回自增长的主键
        spuDetail.setSpuId(spuBo.getId());
        this.spuDetailMapper.insertSelective(spuDetail);

        //新增sku
        //新增库存
        saveSkuAndStock(spuBo);

        //消息同步
        sendMessage(spuBo.getId(),"insert");
    }

    //同步Sku和Stock
    private void saveSkuAndStock(SpuBo spuBo){
        //新增sku
        spuBo.getSkus().forEach(sku -> {
            //新增sku
            sku.setSpuId(spuBo.getId());
            sku.setCreateTime(spuBo.getCreateTime());
            sku.setLastUpdateTime(spuBo.getLastUpdateTime());
            this.skuMapper.insertSelective(sku);

            //新增库表
            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            //数据库sku中并无库存字段，业务中sku实体对之做了扩展
            stock.setStock(sku.getStock());
            this.stockMapper.insertSelective(stock);

        });
        }


    //根据spuId查询spuDetail
    public SpuDetail querySpuDetailBySpuId(Long spuId){
        return this.spuDetailMapper.selectByPrimaryKey(spuId);
    }

    //根据spuId查询skus
    public List<Sku> querySkusBySpuId(Long spuId){
        Sku sku = new Sku();
        sku.setSpuId(spuId);
        List<Sku> skus = this.skuMapper.select(sku);
        //为了页面回显方便，我们一并把sku的库存stock也查询出来
        skus.forEach(s->{
            Stock stock = this.stockMapper.selectByPrimaryKey(s.getId());
            s.setStock(stock.getStock());
        });
        return skus;
    }

    //修改商品
    @Transactional
    //spu数据可以修改，但是SKU数据无法修改。 因为内存实时变化
    //所以SKU的策略就是删除该商品的所有SKU信息，再根据前端传过来的数据重新设置SKU
    public void updateGoods(SpuBo spuBo){

        //查询之前的SKU
        List<Sku> skus = this.querySkusBySpuId(spuBo.getId());

            //删除sku的库存信息
            for (Sku sku : skus) {
                this.stockMapper.deleteByPrimaryKey(sku.getId());
            }

            //删除sku
            //根据sku的spu_id可以一次删除该spu下的所有sku
            Sku sku = new Sku();
            sku.setSpuId(spuBo.getId());
            this.skuMapper.delete(sku);

            //新增sku和库存
            saveSkuAndStock(spuBo);

            //更新spu
            spuBo.setLastUpdateTime(new Date());
            //以下保证不会覆盖原有字段
            spuBo.setCreateTime(null);
            spuBo.setValid(null);
            spuBo.setSaleable(null);
            this.spuMapper.updateByPrimaryKeySelective(spuBo);

            //更新spu_detail
            this.spuDetailMapper.updateByPrimaryKeySelective(spuBo.getSpuDetail());

            //数据同步
            sendMessage(spuBo.getId(),"update");
    }



    public Spu querySpuById(Long id) {
        return this.spuMapper.selectByPrimaryKey(id);
    }


    //抽象MQ发送消息方法
    public void sendMessage(Long id, String type){
        //发送消息
        //数据同步业务不能影响数据正常增删改业务
        try {
            this.amqpTemplate.convertAndSend("item." + type,id);
        }catch (Exception e){
            System.out.println(id + type + "出错了");
        }
    }


    public Sku querySkuById(Long id) {
        return this.skuMapper.selectByPrimaryKey(id);
    }

    //后期改成
    public List<Sku> querySkusByList(List<Long> ids) {
        // == query/... wrapper
        Example example = new Example(Sku.class);
        example.createCriteria().andIn("id", ids);
        return this.skuMapper.selectByExample(example);
    }


    //所有sku图片地址修改
    public void modifyAll() {
        List<Sku> skus = this.skuMapper.selectAll();
        skus.forEach( s -> {
            String replace = s.getImages().replace("http", "https").replace("image.leyou.com", "jshop-item-img.oss-cn-beijing.aliyuncs.com/static");
            s.setImages(replace);
            this.skuMapper.updateByPrimaryKey(s);
        });
    }

    /**
     * @Description 库存递减
     * @Param [map]
     * @return void
     * @Date  2021/11/9
     **/
    public void decrementStock(Map<String, Integer> map){

        //方案探讨
        // 1.查询  库存 > 递减量 >> 多线程问题  行锁解决
        //
        Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            Long skuId = Long.valueOf(next.getKey());
            Integer decrNum = next.getValue();
            int rows = this.stockMapper.decreCount(skuId, decrNum);
            if (rows <= 0){
                //库存不足
                throw new RuntimeException("库存不足");
            }
        }
    }



    }






